import '../../domain/repositories/auth_repository.dart';
import '../datasources/remote/auth_api_service.dart';
import '../datasources/local/auth_local_data_source.dart';
import '../models/user_model.dart';
import '../models/api_response.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:dio/dio.dart';

/// 认证仓储实现类
class AuthRepositoryImpl implements AuthRepository {
  final AuthApiService _apiService;
  final AuthLocalDataSource _localDataSource;

  AuthRepositoryImpl(this._apiService, this._localDataSource);

  @override
  Future<LoginResponse> login(LoginRequest request) async {
    try {
      // 首先检查网络连接状态
      final connectivityResult = await Connectivity().checkConnectivity();
      final isOnline =
          connectivityResult.contains(ConnectivityResult.none) == false;

      if (isOnline) {
        // 在线模式：尝试远程登录
        print('在线模式登录: username=${request.username}');
        final response = await _apiService.login(request);

        if (response.success && response.data != null) {
          final loginData = response.data!;

          // 保存登录信息到本地
          print('在线登录成功，保存登录信息到本地');
          await _localDataSource.saveLoginData(
            token: loginData.token,
            refreshToken: loginData.refreshToken,
            userInfo: loginData.user,
          );

          return loginData;
        } else {
          print('在线登录失败: ${response.message}');
          throw BusinessException(
            message: response.message ?? '登录失败',
            code: response.code,
          );
        }
      } else {
        // 离线模式：检查本地是否有存储的用户信息
        print('离线模式登录: username=${request.username}');
        final storedToken = await _localDataSource.getToken();
        final storedUserInfo = await _localDataSource.getUserInfo();

        print('本地存储的Token: $storedToken');
        print('本地存储的用户信息: $storedUserInfo');

        if (storedToken != null && storedUserInfo != null) {
          // 有本地存储的认证信息，构造登录响应
          print('使用本地存储的认证信息进行离线登录');
          final loginData = LoginResponse(
            token: storedToken,
            refreshToken: await _localDataSource.getRefreshToken() ?? '',
            tokenType: 'Bearer', // 默认token类型
            expiresIn: 3600, // 默认1小时过期
            user: storedUserInfo,
          );

          return loginData;
        } else {
          // 没有本地存储的认证信息，无法离线登录
          print('离线登录失败：无本地认证信息');
          throw NetworkException(
            message: '无网络连接且无本地认证信息',
            originalError: Exception('Offline login failed'),
          );
        }
      }
    } on DioException catch (e) {
      print('登录过程中发生Dio异常: $e');
      // 特别处理连接错误
      if (e.type == DioExceptionType.connectionError) {
        throw NetworkException(
          message: '网络连接失败，请检查网络设置或稍后重试',
          originalError: e,
        );
      }
      rethrow;
    } catch (e) {
      print('登录过程中发生异常: $e');
      if (e is BusinessException) rethrow;
      if (e is NetworkException) rethrow;
      throw NetworkException(
        message: '登录失败：${e.toString()}',
        originalError: e,
      );
    }
  }

  @override
  Future<LoginResponse> refreshToken() async {
    try {
      final response = await _apiService.refreshToken();

      if (response.success && response.data != null) {
        final loginData = response.data!;

        // 更新本地Token
        await _localDataSource.saveToken(loginData.token);

        return loginData;
      } else {
        throw BusinessException(
          message: response.message,
          code: response.code,
        );
      }
    } catch (e) {
      if (e is BusinessException) rethrow;
      throw NetworkException(
        message: 'Token刷新失败：${e.toString()}',
        originalError: e,
      );
    }
  }

  @override
  Future<void> logout({bool clearLocalData = false}) async {
    try {
      // 先调用远程登出接口
      await _apiService.logout();
    } catch (e) {
      // 即使远程登出失败，也不要清除本地数据
      print('远程登出失败: $e');
    } finally {
      // 根据参数决定是否清除本地认证数据
      // 默认情况下不清理本地数据，以支持离线登录
      if (clearLocalData) {
        // 清除本地认证数据
        await _localDataSource.clearAuthData();
      } else {
        // 不清除本地数据，但更新登录状态
        await _localDataSource.setLoggedInStatus(false);
      }
    }
  }

  @override
  Future<bool> validateToken() async {
    try {
      final response = await _apiService.validateToken();
      return response.success && (response.data ?? false);
    } catch (e) {
      return false;
    }
  }

  @override
  Future<UserInfo> getCurrentUser({bool forceUpdate = false}) async {
    try {
      // 首先检查网络连接状态
      final connectivityResult = await Connectivity().checkConnectivity();
      final isOnline =
          connectivityResult.contains(ConnectivityResult.none) == false;

      if (isOnline) {
        // 在线模式：从服务器获取用户信息
        final response = await _apiService.getCurrentUser();

        if (response.success) {
          // 即使data为null，也要处理这种情况
          if (response.data != null) {
            final userInfo = response.data!;

            // 更新本地用户信息
            await _localDataSource.saveUserInfo(userInfo);

            return userInfo;
          } else if (!forceUpdate) {
            // 如果服务器返回的用户信息为null，但不是强制更新，尝试从本地获取
            final storedUserInfo = await _localDataSource.getUserInfo();
            if (storedUserInfo != null) {
              return storedUserInfo;
            } else {
              throw BusinessException(
                message: '无法获取用户信息',
                code: response.code,
              );
            }
          } else {
            throw BusinessException(
              message: '无法获取用户信息',
              code: response.code,
            );
          }
        } else {
          if (!forceUpdate) {
            // 如果API调用失败，但不是强制更新，尝试从本地获取
            final storedUserInfo = await _localDataSource.getUserInfo();
            if (storedUserInfo != null) {
              return storedUserInfo;
            }
          }
          throw BusinessException(
            message: response.message,
            code: response.code,
          );
        }
      } else if (!forceUpdate) {
        // 离线模式：从本地存储获取用户信息
        final storedUserInfo = await _localDataSource.getUserInfo();

        if (storedUserInfo != null) {
          return storedUserInfo;
        } else {
          throw NetworkException(
            message: '无网络连接且无本地用户信息',
            originalError: Exception('Offline get current user failed'),
          );
        }
      } else {
        throw NetworkException(
          message: '无网络连接，无法获取最新用户信息',
          originalError: Exception('Offline get current user failed'),
        );
      }
    } catch (e) {
      // 改进错误处理，提供更友好的错误消息
      if (e is BusinessException) rethrow;
      if (e is NetworkException) rethrow;

      // 检查是否为连接错误
      if (e.toString().contains('SocketException') ||
          e.toString().contains('Connection refused') ||
          e.toString().contains('远程计算机拒绝网络连接')) {
        // 如果不是强制更新，尝试从本地获取
        if (!forceUpdate) {
          try {
            final storedUserInfo = await _localDataSource.getUserInfo();
            if (storedUserInfo != null) {
              return storedUserInfo;
            }
          } catch (innerE) {
            // 静默处理内部错误
          }
        }

        throw NetworkException(
          message: '网络连接失败，请检查网络设置或稍后重试',
          originalError: e,
        );
      }

      throw NetworkException(
        message: '获取用户信息失败：${e.toString()}',
        originalError: e,
      );
    }
  }

  @override
  Future<bool> isLoggedIn() async {
    return await _localDataSource.isLoggedIn();
  }

  @override
  Future<String?> getStoredToken() async {
    return await _localDataSource.getToken();
  }

  @override
  Future<UserInfo?> getStoredUserInfo() async {
    return await _localDataSource.getUserInfo();
  }

  @override
  Future<void> saveUserInfo(UserInfo userInfo) async {
    await _localDataSource.saveUserInfo(userInfo);
  }

  @override
  Future<void> clearAuthData() async {
    await _localDataSource.clearAuthData();
  }

  /// 检查并刷新Token（如果需要的话）
  Future<bool> checkAndRefreshToken() async {
    try {
      final isLoggedIn = await this.isLoggedIn();
      if (!isLoggedIn) return false;

      final isTokenValid = await validateToken();
      if (isTokenValid) return true;

      // Token无效，尝试刷新
      final isExpiringSoon = await _localDataSource.isTokenExpiringSoon();
      if (isExpiringSoon) {
        await refreshToken();
        return true;
      }

      return false;
    } catch (e) {
      // 刷新失败，清除认证数据
      await clearAuthData();
      return false;
    }
  }
}
